package apis

import (
	"encoding/json"
	"fmt"
	"gitee.com/sansaniot/ssiot-core/facade/env"
	"gitee.com/sansaniot/ssiot-core/httpmvc/api"
	"gitee.com/sansaniot/ssiot-core/httpmvc/jwtauth/user"
	"gitee.com/sansaniot/ssiot-core/serrors"
	"github.com/gin-gonic/gin"
	"ssadmin/common/constant"
	"ssadmin/internal/admin/models"
	"ssadmin/internal/admin/models/command"
	"ssadmin/internal/admin/models/query"
	"ssadmin/internal/admin/service"
	cache "ssadmin/internal/admin/utils"
	"time"
)

type User struct {
	api.Api
}

// FindList 获取用户信息列表
func (e User) FindList(c *gin.Context) {
	req := query.UserQuery{}
	m := models.User{}
	err := e.MakeContext(c).Bind(&req).MakeModel(&m.Model).Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	userName := user.Get(c, constant.CacheKeyUserName).(string)
	userId := user.Get(c, constant.CacheKeyUserId).(string)
	req.DeptIds = cache.GetUserDeptIds(userName)
	req.CreatorId = userId

	list := make([]models.User, 0)
	var count int64

	err = m.GetPage(&req, &list, &count)
	if err != nil {
		e.Fail(serrors.Fail)
		return
	}

	e.Page(count, req.GetPageSize(), req.GetPageIndex(), list)
}

// FindCurList 递归获取用户信息列表
func (e User) FindCurList(c *gin.Context) {
	req := query.UserQuery{}
	m := models.User{}
	err := e.MakeContext(c).Bind(&req).MakeModel(&m.Model).Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	userName := user.Get(c, constant.CacheKeyUserName).(string)
	userId := user.Get(c, constant.CacheKeyUserId).(string)
	req.DeptIds = cache.GetUserDeptIds(userName)
	req.CreatorId = userId

	list := make([]models.User, 0)
	var count int64

	err = m.GetRecurPage(&req, &list, &count)
	if err != nil {
		e.Fail(serrors.Fail)
		return
	}
	e.Data(list)
}

// GetProfile 获取用户信息
func (e User) GetProfile(c *gin.Context) {
	req := query.UserGetReq{}
	u := models.User{}

	err := e.MakeContext(c).Bind(&req).MakeModel(&u.Model).Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	// 不传任何参数，获取当前登录用户
	currentUserId := user.Get(c, constant.CacheKeyUserId).(string)
	currentUserName := user.Get(c, constant.CacheKeyUserName).(string)

	if len(req.UserId) == 0 && len(req.Username) == 0 {
		req.UserId = currentUserId
		req.Username = currentUserName
	}

	if err = u.GetProfile(&req, currentUserName); err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}

	e.Data(&u)
}

func (e User) CheckCode(c *gin.Context) {
	req := command.PasswordForgetResetReq{}
	s := service.User{}

	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	if len(req.Mobile) == 0 || len(req.Code) == 0 {
		e.Fail(serrors.InvalidParam)
		return
	}

	// 查询该手机用户
	userInfo := models.User{}
	s.GetByUsername(req.Mobile, &userInfo)

	if len(userInfo.UserId) == 0 || req.Mobile != userInfo.Mobile {
		e.Fail(serrors.WrongPhoneNumber)
		return
	}

	// 验证码核验
	if err = s.CheckCode(&req); err != nil {
		e.Logger.Error(err)
		e.Fail(0, err.Error())
		return
	}

	// 修改密码
	passwdUpdateReq := &command.PasswordUpdateReq{
		Username:    userInfo.Username,
		NewPassword: req.Password,
	}

	err = s.UpdatePwdByPhone(passwdUpdateReq)

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.UpdateFail)
	} else {
		e.Ok(userInfo.UserId)
	}
}

// ResetPassword 管理员重置密码
func (e User) ResetPassword(c *gin.Context) {
	req := command.PasswordResetReq{}
	s := service.User{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	if user.Get(c, constant.CacheKeyCreator) != "admin" {
		e.Fail(0, "无权限")
		return
	}

	if err = s.ResetPassword(req.Username, req.Password); err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}
	e.Data(serrors.OK)
}

// UpdatePassword 重置密码
func (e User) UpdatePassword(c *gin.Context) {
	req := command.PasswordUpdateReq{}
	s := service.User{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.InvalidParam)
		return
	}

	req.Username = user.Get(c, constant.CacheKeyUserName).(string)
	if err = s.UpdatePwd(&req); err != nil {
		e.Fail(serrors.WrongPassword)
		return
	}

	e.Ok(true)
}

// Insert 创建用户信息
func (e User) Insert(c *gin.Context) {
	req := command.UserInsertReq{}
	s := service.User{}

	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.InvalidParam)
		return
	}

	if len(req.Username) < 6 {
		e.Fail(0, "登录账号至少6个英文字符或2个中文字符")
		return
	}

	//获取扩展属性（自定义扩展）
	userId := user.Get(c, constant.CacheKeyUserId).(string)
	req.UserId = userId
	req.Creator = user.Get(c, constant.CacheKeyUserName).(string)
	req.CreatorId = userId
	req.CreateTime = time.Now()
	agencyId := user.Get(c, constant.CacheKeyAgencyId)

	if len(req.DeptIds) == 0 {
		e.Logger.Error("no deptIds")
		e.Fail(serrors.InvalidParam)
		return
	}

	if agencyId != nil {
		req.Agency = agencyId.(string)
	}

	err = s.Insert(&req)
	if err != nil {
		e.Fail(serrors.Fail)
		return
	}

	e.Data(req.GetId())
}

// Update 修改用户信息
func (e User) Update(c *gin.Context) {
	req := command.UserUpdateReq{}
	s := service.User{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	err = s.Update(&req)
	if err != nil {
		e.Fail(serrors.Fail)
		return
	}

	e.Data(req.GetId())
}

// Delete 删除用户信息
func (e User) Delete(c *gin.Context) {
	s := service.User{}
	req := command.UserDeleteReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		MakeService(&s.Service).
		Errors
	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}

	req.CurrentUserId = user.Get(c, constant.CacheKeyUserId).(string)
	err = s.Remove(&req)
	if err != nil {
		e.Fail(serrors.Fail)
		return
	}

	e.Data(req.GetId())
}

// QrCodeCache 扫码登录二维码缓存
func (e User) QrCodeCache(c *gin.Context) {
	req := command.QrCodeCacheReq{}
	err := e.MakeContext(c).
		MakeOrm().
		Bind(&req).
		Errors

	if err != nil {
		e.Logger.Error(err)
		e.Fail(serrors.Fail)
		return
	}
	//token := c.GetHeader("Authentication")
	//缓存二维码信息
	cacheKey := fmt.Sprintf("%s%s", constant.PrefixQrCodeInfo, req.QrCode)
	cacheVal := make(map[string]interface{})
	cacheVal["qrCode"] = req.QrCode
	//cacheVal["token"] = token
	//userInfo, _ := c.Get(constant.CacheKeyUserInfo)
	//cacheVal["user"] = userInfo
	cacheVal["username"] = user.Get(c, constant.CacheKeyUserName).(string)

	bytes, _ := json.Marshal(cacheVal)
	env.Cache.Set(cacheKey, string(bytes), 300)
	e.Data(serrors.OK)
}
